local tinsert = table.insert

--生成分页数据


local Pagination = {}

function Pagination:new(options)
    options = options or {}
    local instance = {
        currentPage = options.currentPage,
        totalItems = options.totalItems,
        itemsPerPage = options.itemsPerPage,
        action = options.action,
        params = options.params,
        firstPage = options.firstPage or 1,
        rangeLength = options.rangeLength or 5,
        firstLabel = options.firstLabel or '首页',
        previousLabel = options.previousLabel or '上一页',
        nextLabel = options.nextLabel or '下一页',
        lastLabel = options.lastLabel or '尾页'
    }


    setmetatable(instance, { __index = self })
    return instance
end


function Pagination:getPage()
    self.offset = self:getOffset()
    self.totalPages = self:getTotal()
    self.lastPage = self.firstPage + self.totalPages - 1
    self.nextPage = self:getNext()
    self.previousPage = self:getPrevious()
    self.rangeStart = self:getRangeStart()
    self.rangeEnd = self:getRangeEnd()
    self.range = self:getRange()
    return self.range
end

function Pagination:getOffset()
    return math.floor(self.rangeLength / 2);
end

function Pagination:getTotal()
    return math.ceil(self.totalItems / self.itemsPerPage);
end


function Pagination:getNext()
    local next = self.currentPage + 1;
    if next > self.lastPage then
        return nil
    else
        return next
    end
end

-- get previous page
function Pagination:getPrevious()
    local previous = self.currentPage - 1
    if previous < self.firstPage then
        return nil
    else
        return previous
    end
end


-- get first item of the range
function Pagination:getRangeStart()
    local rangeStart;
    rangeStart = self.currentPage - self.offset

    if self.lastPage < rangeStart + self.rangeLength then
        rangeStart = self.lastPage - self.rangeLength + 1
    else
        rangeStart = rangeStart
    end


    if rangeStart < self.firstPage then
        rangeStart = self.firstPage
    else
        rangeStart = rangeStart
    end

    return rangeStart
end

--- get first item of the range
function Pagination:getRangeEnd()
    local rangeEnd;

    rangeEnd = self.currentPage + self.offset

    if rangeEnd < self.rangeLength then
        rangeEnd = self.rangeLength
    else
        rangeEnd = rangeEnd
    end

    if rangeEnd > self.lastPage then
        rangeEnd = self.lastPage
    else
        rangeEnd = rangeEnd
    end

    return rangeEnd;
end


-- get range array
function Pagination:getRange()
    local range = {}
    local i = self.rangeStart;
    local t = self.rangeEnd;

    if self.firstPage ~= self.currentPage then
        tinsert(range, { page = self.firstPage, isFirst = true, label = self.firstLabel ,path = self:getUrl(self.firstPage)})
    end

    if self.previousPage then
        tinsert(range, { page = self.previousPage, isPrevious = true, label = self.previousLabel,path = self:getUrl(self.previousPage) })
    end

    for h = i, t do
        local item = { page = h ,label = h,path = self:getUrl(h)};
        if h == self.currentPage then
            item.isCurrent = true;
        end
        tinsert(range, item)
    end

    if self.nextPage then
        tinsert(range, { page = self.nextPage, isNext = true, label = self.nextLabel,path = self:getUrl(self.nextPage) })
    end

    if self.lastPage ~= self.currentPage and self.totalItems > 0 then
        tinsert(range, { page = self.lastPage, isLast = true, label = self.lastLabel ,path = self:getUrl(self.lastPage) })
    end

    return range;
end

-----------------------------------------完美分割线---------------------------------------------------------
--local page_param = req.uri_args
--page_param.page = 2
--local query = Pagination.encode(page_param)
--print_r(query)
function Pagination.encode(value)
    if type(value) == 'table' then
        local names = {}
        for name in pairs(value) do
            table.insert(names, name)
        end
        table.sort(names)

        local buffer = {}
        for _, name in ipairs(names) do
            table.insert(buffer, Pagination.encode(name) .. '=' .. Pagination.encode(value[name]))
        end
        return table.concat(buffer, '&')
    elseif type(value) == 'string' then
        return (value:gsub('[^%w]', function(c)
            return string.format('%%%02X', string.byte(c))
        end))
    elseif type(value) == 'nil' then
        return ''
    else
        return Pagination.encode(tostring(value))
    end
end


function Pagination:getUrl(page)
    local action = self.action
    local params = self.params
    --设置当前页数
    params.page = page
    local query_string = self.encode(params)
    return action..'?'..query_string
end


return Pagination

